﻿#region Copyright information
// 
// Copyright © 2005-2013 Yongkee Cho. All rights reserved.
// 
// This code is a part of the Biological Object Library and governed under the terms of the
// GNU Lesser General  Public License (LGPL) version 2.1 which accompanies this distribution.
// For more information on the LGPL, please visit http://bol.codeplex.com/license.
// 
// - Filename: OneSampleProportionTest.cs
// - Author: Yongkee Cho
// - Email: yongkeecho@gmail.com
// - Date Created: 2012-09-06 11:39 AM
// - Last Modified: 2013-01-25 3:59 PM
// 
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using BOL.Maths.Distributions;

namespace BOL.Maths.Statistics.HypothesisTest
{
    public sealed class OneSampleProportionTest : OneSampleTestBase<bool>
    {
        #region Private variables

        private readonly int _numberOfSuccess;

        #endregion
        
        #region Constructors

        public OneSampleProportionTest(TestType type, double alpha, double p0, int sampleSize, int numberOfSuccess)
            : base(type, alpha, p0, Enumerable.Repeat(true, numberOfSuccess).Concat(Enumerable.Repeat(false, sampleSize - numberOfSuccess)))
        {
            _numberOfSuccess = numberOfSuccess;
            Distribution = new GaussianDistribution();
        }
        
        public OneSampleProportionTest(TestType type, double p12, int sampleSize, int numberOfSuccess) : this(type, 0.05, p12, sampleSize, numberOfSuccess) { }

        public OneSampleProportionTest(double alpha, double p12, int sampleSize, int numberOfSuccess) : this(TestType.TwoSided, alpha, p12, sampleSize, numberOfSuccess) { }

        public OneSampleProportionTest(double p12, int sampleSize, int numberOfSuccess) : this(TestType.TwoSided, 0.05, p12, sampleSize, numberOfSuccess) { }

        public OneSampleProportionTest(TestType type, double alpha, double p0, IEnumerable<bool> sample)
            : base(type, alpha, p0, sample)
        {
            _numberOfSuccess = Sample.Count(x => x);
            Distribution = new GaussianDistribution();
        }

        public OneSampleProportionTest(TestType type, double p12, IEnumerable<bool> sample) : this(type, 0.05, p12, sample) { }

        public OneSampleProportionTest(double alpha, double p12, IEnumerable<bool> sample) : this(TestType.TwoSided, alpha, p12, sample) { }

        public OneSampleProportionTest(double p12, IEnumerable<bool> sample) : this(TestType.TwoSided, 0.05, p12, sample) { }

        #endregion

        #region Protected methods

        protected override double PointEstimate()
        {
            return _numberOfSuccess / (double)SampleSize;
        }

        protected override double PointEstimateStandardError()
        {
            var pi = PointEstimate();

            return Math.Sqrt(pi * (1 - pi) / SampleSize);
        }

        #endregion
    }
}
